/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 actor_model_definition.h

	$Header: /heroes4/actor_model_definition.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( ACTOR_MODEL_DEFINITION_H_INCLUDED )
#define ACTOR_MODEL_DEFINITION_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#pragma warning( disable: 4786 ) // Disable the ever so helpful "identifier was truncated to '255' characters" warning

#include <cassert>
#include <cstddef>
#include <string>

#include "direction.h"
#include "screen_point.h"
#include "static_vector.h"

// ------------------------------------------------------------------------------
// t_actor_action_definition class
// ------------------------------------------------------------------------------

class t_actor_action_definition
{
public:
	// Constructor
	t_actor_action_definition();

	// Member functions
	int					get_frames_per_second() const;
	std::string const &	get_sequence_name( t_direction direction ) const;
	void				set_frames_per_second( int new_frames_per_second );
	void				set_sequence_name( t_direction direction, std::string const & new_sequence_name );

private:
	// Data members
	int													m_frames_per_second;
	t_static_vector< std::string, k_direction_count >	m_sequence_name_array;
};

inline t_actor_action_definition::t_actor_action_definition()
	:	m_frames_per_second( 10 )
{
}

inline int t_actor_action_definition::get_frames_per_second() const
{
	return m_frames_per_second;
}

inline std::string const & t_actor_action_definition::get_sequence_name( t_direction direction ) const
{
	assert( direction >= 0 && direction < k_direction_count );
	return m_sequence_name_array[ direction ];
}

inline void t_actor_action_definition::set_frames_per_second( int new_frames_per_second )
{
	assert( new_frames_per_second >= 1 && new_frames_per_second <= 50 );
	m_frames_per_second = new_frames_per_second;
}

inline void t_actor_action_definition::set_sequence_name( t_direction direction, std::string const & new_sequence_name )
{
	assert( direction >= 0 && direction < k_direction_count );
	m_sequence_name_array[ direction ] = new_sequence_name;
}

// ------------------------------------------------------------------------------
// t_actor_model_definition_base class
// ------------------------------------------------------------------------------

class t_actor_model_definition_base
{
public:
	// Constructor/Destructor
	t_actor_model_definition_base();
	virtual ~t_actor_model_definition_base();

	// Member functions
	t_screen_point const &	get_offset() const;
	int						get_postwalk_length() const;
	int						get_prewalk_length() const;
	int						get_walk_length() const;
	void					set_postwalk_length( int arg );
	void					set_prewalk_length( int arg );
	void					set_walk_length( int arg );
	void					set_offset( t_screen_point const & new_offset );
private:
	// Data members
	t_screen_point	m_offset;
	int				m_prewalk_length;
	int				m_walk_length;
	int				m_postwalk_length;
};

inline t_actor_model_definition_base::t_actor_model_definition_base()
	:	m_offset( 0, 0 )
{
}

inline t_actor_model_definition_base::~t_actor_model_definition_base()
{
}

inline t_screen_point const & t_actor_model_definition_base::get_offset() const
{
	return m_offset;
}

inline int t_actor_model_definition_base::get_postwalk_length() const
{
	return m_postwalk_length;
}

inline int t_actor_model_definition_base::get_prewalk_length() const
{
	return m_prewalk_length;
}

inline int t_actor_model_definition_base::get_walk_length() const
{
	return m_walk_length;
}

inline void t_actor_model_definition_base::set_offset( t_screen_point const & new_offset )
{
	m_offset = new_offset;
}

inline void t_actor_model_definition_base::set_postwalk_length( int arg )
{
	m_postwalk_length = arg;
}

inline void t_actor_model_definition_base::set_prewalk_length( int arg )
{
	m_prewalk_length = arg;
}

inline void t_actor_model_definition_base::set_walk_length( int arg )
{
	m_walk_length = arg;
}

// ------------------------------------------------------------------------------
// t_actor_model_definition class template
// ------------------------------------------------------------------------------

template < typename t_traits >
class t_actor_model_definition : public t_actor_model_definition_base
{
public:
	// Types
	typedef typename t_traits::t_action_id	t_action_id;
	typedef t_actor_action_definition		t_action_definition;

	// Static data
	enum { k_action_count = t_traits::k_action_count };
	enum { k_cell_width = t_traits::k_cell_width };
	enum { k_cell_height = t_traits::k_cell_height };
	enum { k_max_footprint_size = t_traits::k_max_footprint_size };
	enum { k_min_footprint_size = t_traits::k_min_footprint_size };

	// Constructor/Destructor
	t_actor_model_definition();
	virtual ~t_actor_model_definition();

	// Member functions
	int					get_footprint_size() const;
	int					get_frames_per_second( t_action_id action_id ) const;
	std::string const &	get_sequence_name(
							t_action_id	action_id,
							t_direction	direction ) const;
	void				set_footprint_size( int new_footprint_size );
	void				set_frames_per_second(
							t_action_id	action_id,
							int			new_frames_per_second );
	void				set_sequence_name(
							t_action_id			action_id,
							t_direction			direction,
							std::string const &	new_sequence_name );

private:
	// Data members
	int														m_footprint_size;
	t_static_vector< t_action_definition, k_action_count >	m_action_array;
};

template < typename t_traits >
inline t_actor_model_definition< t_traits >::t_actor_model_definition()
	:	m_footprint_size( k_min_footprint_size )
{
}

template < typename t_traits >
inline t_actor_model_definition< t_traits >::~t_actor_model_definition()
{
}

template < typename t_traits >
inline int t_actor_model_definition< t_traits >::get_footprint_size() const
{
	return m_footprint_size;
}

template < typename t_traits >
inline int t_actor_model_definition< t_traits >::get_frames_per_second(
	t_action_id action_id ) const
{
	assert( action_id >= 0 && action_id < k_action_count );
	return m_action_array[ action_id ].get_frames_per_second();
}

template < typename t_traits >
inline std::string const & t_actor_model_definition< t_traits >::get_sequence_name(
	t_action_id	action_id,
	t_direction	direction ) const
{
	assert( action_id >= 0 && action_id < k_action_count );
	return m_action_array[ action_id ].get_sequence_name( direction );
}

template < typename t_traits >
inline void t_actor_model_definition< t_traits >::set_footprint_size( int new_footprint_size )
{
	assert(		new_footprint_size >= k_min_footprint_size
			&&	new_footprint_size <= k_max_footprint_size );
	m_footprint_size = new_footprint_size;
}

template < typename t_traits >
inline void t_actor_model_definition< t_traits >::set_frames_per_second(
	t_action_id	action_id,
	int			new_frames_per_second )
{
	assert( action_id >= 0 && action_id < k_action_count );
	m_action_array[ action_id ].set_frames_per_second( new_frames_per_second );
}

template < typename t_traits >
inline void t_actor_model_definition< t_traits >::set_sequence_name(
	t_action_id			action_id,
	t_direction			direction,
	std::string const &	new_sequence_name )
{
	assert( action_id >= 0 && action_id < k_action_count );
	m_action_array[ action_id ].set_sequence_name( direction, new_sequence_name );
}

#endif // !defined( ACTOR_MODEL_DEFINITION_H_INCLUDED )
